"""
导出模块
支持Markdown、Word、JSON格式导出
"""

import json
import os
from datetime import datetime
from pathlib import Path
from typing import List, Dict, Any, Optional
from dataclasses import asdict
import markdown
from docx import Document
from docx.shared import Inches
from jinja2 import Template

from ..core import config, storage_logger
from ..postprocessing import ProcessedText, TextSegment, SourceType


class BaseExporter:
    """导出器基类"""
    
    def __init__(self):
        self.output_dir = Path(config.export.output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.template_dir = Path(config.export.template_dir)
        
    def export(self, meeting_data: Dict[str, Any], output_path: str) -> bool:
        """导出数据"""
        raise NotImplementedError
    
    def _sanitize_filename(self, filename: str) -> str:
        """清理文件名"""
        invalid_chars = '<>:"/\\|?*'
        for char in invalid_chars:
            filename = filename.replace(char, '_')
        return filename


class MarkdownExporter(BaseExporter):
    """Markdown导出器"""
    
    def __init__(self):
        super().__init__()
        self.template = self._load_template()
    
    def _load_template(self) -> Template:
        """加载Markdown模板"""
        template_content = """# {{ meeting.title }}

**会议ID**: {{ meeting.meeting_id }}
**开始时间**: {{ meeting.start_time }}
**结束时间**: {{ meeting.end_time }}
**状态**: {{ meeting.status }}

{% if meeting.description %}
**描述**: {{ meeting.description }}
{% endif %}

---

## 会议内容

{% for source_type, segments in segments_by_type.items() %}
### {{ source_type_names[source_type] }}

{% for segment in segments %}
#### 时间段: {{ segment.start_time }} - {{ segment.end_time }}
**置信度**: {{ "%.2f"|format(segment.confidence) }}

{{ segment.content }}

{% if segment.keywords %}
**关键词**: {{ segment.keywords|join(', ') }}
{% endif %}

---
{% endfor %}
{% endfor %}

## 统计信息

- **总段落数**: {{ segments|length }}
- **总文本数**: {{ texts|length }}
- **平均置信度**: {{ "%.2f"|format(average_confidence) }}

{% if texts_by_type %}
### 按类型统计

{% for source_type, count in texts_by_type.items() %}
- **{{ source_type_names[source_type] }}**: {{ count }} 条
{% endfor %}
{% endif %}

---

*导出时间: {{ export_time }}*
"""
        return Template(template_content)
    
    def export(self, meeting_data: Dict[str, Any], output_path: Optional[str] = None) -> bool:
        """导出为Markdown格式"""
        try:
            meeting = meeting_data.get('meeting', {})
            texts = meeting_data.get('texts', [])
            segments = meeting_data.get('segments', [])
            
            # 按类型分组段落
            segments_by_type = {}
            for segment in segments:
                source_type = segment.get('source_type', 'unknown')
                if source_type not in segments_by_type:
                    segments_by_type[source_type] = []
                segments_by_type[source_type].append(segment)
            
            # 统计信息
            texts_by_type = {}
            total_confidence = 0
            for text in texts:
                source_type = text.get('source_type', 'unknown')
                texts_by_type[source_type] = texts_by_type.get(source_type, 0) + 1
                total_confidence += text.get('confidence', 0)
            
            average_confidence = total_confidence / len(texts) if texts else 0
            
            # 类型名称映射
            source_type_names = {
                'slide': '幻灯片内容',
                'whiteboard': '板书内容',
                'discussion': '讨论记录',
                'unknown': '未知类型'
            }
            
            # 渲染模板
            content = self.template.render(
                meeting=meeting,
                texts=texts,
                segments=segments,
                segments_by_type=segments_by_type,
                texts_by_type=texts_by_type,
                average_confidence=average_confidence,
                source_type_names=source_type_names,
                export_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            )
            
            # 生成文件名
            if not output_path:
                meeting_id = meeting.get('meeting_id', 'unknown')
                filename = f"{self._sanitize_filename(meeting_id)}_meeting_notes.md"
                output_path = self.output_dir / filename
            
            # 写入文件
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write(content)
            
            storage_logger.info(f"Markdown导出成功: {output_path}")
            return True
            
        except Exception as e:
            storage_logger.error(f"Markdown导出失败: {e}")
            return False


class WordExporter(BaseExporter):
    """Word文档导出器"""
    
    def export(self, meeting_data: Dict[str, Any], output_path: Optional[str] = None) -> bool:
        """导出为Word格式"""
        try:
            meeting = meeting_data.get('meeting', {})
            texts = meeting_data.get('texts', [])
            segments = meeting_data.get('segments', [])
            
            # 创建Word文档
            doc = Document()
            
            # 添加标题
            title = meeting.get('title', '会议记录')
            doc.add_heading(title, 0)
            
            # 添加会议信息
            info_table = doc.add_table(rows=0, cols=2)
            info_table.style = 'Table Grid'
            
            info_data = [
                ('会议ID', meeting.get('meeting_id', '')),
                ('开始时间', meeting.get('start_time', '')),
                ('结束时间', meeting.get('end_time', '')),
                ('状态', meeting.get('status', ''))
            ]
            
            if meeting.get('description'):
                info_data.append(('描述', meeting.get('description')))
            
            for label, value in info_data:
                row = info_table.add_row()
                row.cells[0].text = label
                row.cells[1].text = str(value)
            
            doc.add_paragraph()
            
            # 按类型分组并添加内容
            segments_by_type = {}
            for segment in segments:
                source_type = segment.get('source_type', 'unknown')
                if source_type not in segments_by_type:
                    segments_by_type[source_type] = []
                segments_by_type[source_type].append(segment)
            
            source_type_names = {
                'slide': '幻灯片内容',
                'whiteboard': '板书内容', 
                'discussion': '讨论记录',
                'unknown': '未知类型'
            }
            
            for source_type, type_segments in segments_by_type.items():
                # 添加类型标题
                doc.add_heading(source_type_names.get(source_type, source_type), 1)
                
                for segment in type_segments:
                    # 添加时间信息
                    time_info = f"时间: {segment.get('start_time', '')} - {segment.get('end_time', '')}"
                    confidence_info = f"置信度: {segment.get('confidence', 0):.2f}"
                    doc.add_paragraph(f"{time_info} | {confidence_info}")
                    
                    # 添加内容
                    content_para = doc.add_paragraph(segment.get('content', ''))
                    
                    # 添加关键词
                    keywords = segment.get('keywords', [])
                    if keywords:
                        keyword_para = doc.add_paragraph()
                        keyword_para.add_run('关键词: ').bold = True
                        keyword_para.add_run(', '.join(keywords))
                    
                    doc.add_paragraph()  # 空行分隔
            
            # 添加统计信息
            doc.add_heading('统计信息', 1)
            
            stats_data = [
                f"总段落数: {len(segments)}",
                f"总文本数: {len(texts)}"
            ]
            
            if texts:
                avg_confidence = sum(t.get('confidence', 0) for t in texts) / len(texts)
                stats_data.append(f"平均置信度: {avg_confidence:.2f}")
            
            for stat in stats_data:
                doc.add_paragraph(stat)
            
            # 添加导出时间
            doc.add_paragraph()
            export_time_para = doc.add_paragraph()
            export_time_para.add_run('导出时间: ').italic = True
            export_time_para.add_run(datetime.now().strftime('%Y-%m-%d %H:%M:%S')).italic = True
            
            # 生成文件名
            if not output_path:
                meeting_id = meeting.get('meeting_id', 'unknown')
                filename = f"{self._sanitize_filename(meeting_id)}_meeting_notes.docx"
                output_path = self.output_dir / filename
            
            # 保存文档
            doc.save(output_path)
            
            storage_logger.info(f"Word导出成功: {output_path}")
            return True
            
        except Exception as e:
            storage_logger.error(f"Word导出失败: {e}")
            return False


class JSONExporter(BaseExporter):
    """JSON导出器"""
    
    def export(self, meeting_data: Dict[str, Any], output_path: Optional[str] = None) -> bool:
        """导出为JSON格式"""
        try:
            # 添加导出元数据
            export_data = {
                'export_info': {
                    'export_time': datetime.now().isoformat(),
                    'format_version': '1.0',
                    'exporter': 'MeetingRecognition'
                },
                'meeting': meeting_data.get('meeting', {}),
                'texts': meeting_data.get('texts', []),
                'segments': meeting_data.get('segments', [])
            }
            
            # 添加统计信息
            texts = meeting_data.get('texts', [])
            segments = meeting_data.get('segments', [])
            
            export_data['statistics'] = {
                'total_texts': len(texts),
                'total_segments': len(segments),
                'average_confidence': sum(t.get('confidence', 0) for t in texts) / len(texts) if texts else 0,
                'texts_by_type': {},
                'segments_by_type': {}
            }
            
            # 按类型统计
            for text in texts:
                source_type = text.get('source_type', 'unknown')
                export_data['statistics']['texts_by_type'][source_type] = \
                    export_data['statistics']['texts_by_type'].get(source_type, 0) + 1
            
            for segment in segments:
                source_type = segment.get('source_type', 'unknown')
                export_data['statistics']['segments_by_type'][source_type] = \
                    export_data['statistics']['segments_by_type'].get(source_type, 0) + 1
            
            # 生成文件名
            if not output_path:
                meeting = meeting_data.get('meeting', {})
                meeting_id = meeting.get('meeting_id', 'unknown')
                filename = f"{self._sanitize_filename(meeting_id)}_meeting_data.json"
                output_path = self.output_dir / filename
            
            # 写入JSON文件
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, ensure_ascii=False, indent=2)
            
            storage_logger.info(f"JSON导出成功: {output_path}")
            return True
            
        except Exception as e:
            storage_logger.error(f"JSON导出失败: {e}")
            return False


class ExportManager:
    """导出管理器"""
    
    def __init__(self):
        self.exporters = {
            'markdown': MarkdownExporter(),
            'docx': WordExporter(),
            'json': JSONExporter()
        }
        
        storage_logger.info("导出管理器初始化完成")
    
    def export_meeting(self, meeting_data: Dict[str, Any], 
                      formats: List[str], 
                      output_dir: Optional[str] = None) -> Dict[str, bool]:
        """导出会议数据到多种格式"""
        results = {}
        
        for format_name in formats:
            if format_name not in self.exporters:
                storage_logger.warning(f"不支持的导出格式: {format_name}")
                results[format_name] = False
                continue
            
            try:
                exporter = self.exporters[format_name]
                
                # 设置输出路径
                output_path = None
                if output_dir:
                    meeting = meeting_data.get('meeting', {})
                    meeting_id = meeting.get('meeting_id', 'unknown')
                    
                    if format_name == 'markdown':
                        filename = f"{exporter._sanitize_filename(meeting_id)}_meeting_notes.md"
                    elif format_name == 'docx':
                        filename = f"{exporter._sanitize_filename(meeting_id)}_meeting_notes.docx"
                    elif format_name == 'json':
                        filename = f"{exporter._sanitize_filename(meeting_id)}_meeting_data.json"
                    
                    output_path = Path(output_dir) / filename
                
                # 执行导出
                success = exporter.export(meeting_data, output_path)
                results[format_name] = success
                
            except Exception as e:
                storage_logger.error(f"导出格式 {format_name} 失败: {e}")
                results[format_name] = False
        
        return results
    
    def get_supported_formats(self) -> List[str]:
        """获取支持的导出格式"""
        return list(self.exporters.keys())
